import { defineStore } from 'pinia'
import { ref } from 'vue'
import { ElMessage, ElLoading } from 'element-plus'

export const useCodeStore = defineStore('localCode', () => {
  const userCode = ref('')
  const pyodide = ref('')
  const results = ref('')
  const MAX_EXECUTION_TIME_MS = 5000
  // 封装代码的方法
  // 提供代码输入功能
  // 保存用户的输入
  const userInput = ref('')
  // 1. 将用户在输入框编写的输入格式化成为Python代码的列表格式
  const stringToList = () => {
    let arr = userInput.value.trim().split(/\s+/)
    // let arr = userInput.value.split()
    // 将数组转换为字符串，并添加引号
    let formattedArr = arr.map((item) => `'${item}'`)

    // 将数组转换为字符串，并添加方括号
    let arrStr = `[${formattedArr.join(', ')}]`

    // 返回格式化的字符串
    // console.log(`userDataxb123 = ${arrStr}\n`)
    return `userData123 = ${arrStr}`
  }
  // 2. 提供Python输入流重定向的模板语法
  const generateReStdCode = () => {
    // 拼接重定向的代码
    let pythonCodes = [
      'import builtins',
      'def input_generator(data):',
      '  for item in data:',
      '    yield item',
      `${stringToList()}`,
      'input = input_generator(userData123).__next__'
    ]
    return pythonCodes.join('\n')
  }
  // 3. 提供恢复Python输入流重定向的模板语法
  const generateReset = () => {
    return `input = builtins.input\n`
  }
  // 4. 将input()中的提示词全部删除，否则会报错
  const removePrompt = (inputStr) => {
    // 匹配input函数中的字符串参数，包括单引号和双引号
    let regex = /input\((["'])(.*?)\1\)/
    let match = inputStr.match(regex)

    // 如果找到匹配项，删除提示词和引号
    while ((match = regex.exec(inputStr)) !== null) {
      inputStr = inputStr.replace(`"${match[2]}"`, '').replace(`'${match[2]}'`, '')
    }

    // 如果没有找到匹配项，返回原字符串
    return inputStr
  }

  // 5. 拼接防止超时代码
  const preventTimeout = (indentedUserCode) => {
    // 在代码开头添加开始时间的记录
    let modifiedCode = 'import time\nstartTime = time.time()\n' + indentedUserCode
    let loopCount = 0
    // 使用正则表达式找到所有的循环，并在每个循环的开始处添加超时检查的代码
    modifiedCode = modifiedCode.replace(/(^\s*)(for .*:|while .*:)/gm, (match, p1, p2) => {
      if (loopCount === 0) {
        loopCount+=1
        return match
      }
      // 定义超时检查的代码，根据原始循环的缩进来调整缩进
      const timeoutCheckCode = `
  ${p1}currentTime = time.time()
  ${p1}if(currentTime - startTime) > 2:
  ${p1}  print("执行超时！")
  ${p1}  return\n`

      return `${p1}${p2}${timeoutCheckCode}`
    })

    return modifiedCode
  }
  // 6. 使用上面封装的方法对用户的代码进行处理，同时为代码添加缩进，并且包裹在main()函数里面
  const indentUserCode = () => {
    let myCode
    // 判断是否只运行一个代码块
    myCode = userCode.value
    // myCode = "print('HelloWorld')"
    // console.log('myCode=', myCode)
    // 封装用户的代码
    // 将用户的代码按行分割，然后在每一行的开始添加四个空格
    // 要将输入流重写，同时将用户的输入导入进来
    // 测试输入的格式是否正确
    myCode = `${generateReStdCode()}\n${myCode}`
    let indentedUserCode = myCode
      .split('\n')
      .map((line) => '  ' + line)
      .join('\n')
    indentedUserCode = `def main():\n${indentedUserCode}\n  ${generateReset()}\n`
    // 拼接防止超时代码
    indentedUserCode = preventTimeout(indentedUserCode)
    indentedUserCode = indentedUserCode + '\nmain()'
    // 将input中的输入提示词全部干掉
    indentedUserCode = removePrompt(indentedUserCode)
    // 这里需要拼接一个防止超时的python代码
    // userCode.value = indentedUserCode
    return indentedUserCode
  }

  // =====Python运行环境配置======
  // 1. 获取pyodide
  const getPyodide = async () => {
    return await window.loadPyodide({ indexURL: 'https://cdn.jsdelivr.net/pyodide/v0.18.1/full/' })
  }
  // 2. 初始化Python终端
  const initPython = async () => {
    console.log('Start init...')
    // let num = 0
    const originalConsoleLog = console.log
    results.value = ''
    // 重写console.log函数
    // 目的是将输出流重定向到results变量中
    console.log = function (message) {
      // 将输出添加到consoleOutput变量中
      results.value += message + '\n'
    }
    // 如果不存在，就重新加载Pyodide
    // 使用加载框提示用户正在加载
    const loading = ElLoading.service({
      fullscreen: true,
      text: '正在加载Python环境'
    })
    if (pyodide.value && typeof pyodide.value.runPython === 'function') {
      loading.close()
      return ElMessage({
        message: '当前无需重新初始化Python环境!',
        type: 'warning'
      })
    }
    // num += 1
    try {
      //
      console.log('重新载入了...')
      pyodide.value = null
      pyodide.value = await getPyodide()
    } catch (err) {
      loading.close()
      return ElMessage({
        message: '初始化Python环境失败!请重试!',
        type: 'error'
      })
    }
    // num += 1
    console.log = originalConsoleLog
    console.log('init successfully!')
    loading.close()
    ElMessage({
      message: '初始化Python环境成功!',
      type: 'success'
    })
    // console.log('end Init')
    // console.log(num)
    // return Boolean(pyodide.value)
  }
  initPython()

  const runCode = async () => {
    // ... (保留原有的变量定义和console.log重写部分)
    const originalConsoleLog = console.log

    results.value = ''
    // 重写console.log函数
    console.log = function (message) {
      // 使用原始的console.log函数来输出消息
      // originalConsoleLog.apply(console, arguments)
      // 将输出添加到consoleOutput变量中
      results.value += message + '\n'
    }
    if (!pyodide.value || typeof pyodide.value.runPython !== 'function') {
      await initPython()
    }

    const wrappedCode = indentUserCode()
    const executionPromise = new Promise((resolve, reject) => {
      let isResolved = false
      setTimeout(() => {
        if (!isResolved) {
          reject(new Error('Script execution timed out'))
        }
      }, MAX_EXECUTION_TIME_MS)

      try {
        // userCode.value = wrappedCode
        // console.log('This is wrappedCode', wrappedCode)
        pyodide.value.runPython(wrappedCode)
        isResolved = true
        resolve(results.value) // 如果Python代码正常结束，则解决Promise并返回结果
      } catch (err) {
        isResolved = true
        reject(err) // 如果出现任何错误，通过reject传递错误信息
      } finally {
        console.log = originalConsoleLog
      }
    })

    try {
      const resultOrError = await executionPromise
      if (resultOrError instanceof Error) {
        console.error(`脚本执行异常：${resultOrError.message}`)
      } else {
        // results.value += resultOrError + '\n' // 假设运行结果可以直接转换为字符串
        if(results.value.includes('执行超时')) {
          runningResults.value.type = '运行失败'
          runningResults.value.result = '执行超时'
          ElMessage({
            type:'error',
            message:'运行失败!'
          })
        } else {
          runningResults.value.type = '运行成功'
          runningResults.value.result = results.value
          ElMessage({
            type:'success',
            message:'运行成功!'
          })
        }
      }
    } catch (err) {
      // console.error(`脚本执行期间发生未知错误：${err.message}`)
      results.value = err.message
      // const isRight = '运行失败'
      runningResults.value.type = '运行失败'
      runningResults.value.result = results.value
      ElMessage({
        type:'error',
        message:'运行失败!'
      })
      // saveResult(isRight, results.value)
    }
  }
  // // 运行Python代码
  // const runCode1 = async () => {
  //   const originalConsoleLog = console.log

  //   results.value = ''
  //   // 重写console.log函数
  //   console.log = function (message) {
  //     // 使用原始的console.log函数来输出消息
  //     // originalConsoleLog.apply(console, arguments)
  //     // 将输出添加到consoleOutput变量中
  //     results.value += message + '\n'
  //   }
  //   if (!pyodide.value || typeof pyodide.value.runPython !== 'function') {
  //     // 如果不存在，就重新加载Pyodide
  //     // pyodide.value = await getPyodide()
  //     await initPython()
  //   }
  //   try {
  //     // pyodide.value.runPython('clear')
  //     // pyodide.value.globals = pyodide.value.new_globals()
  //     const wrappedCode = indentUserCode()
  //     // 一定要加await
  //     await pyodide.value.runPython(wrappedCode)
  //   } catch (err) {
  //     console.log(err)
  //   }
  //   console.log = originalConsoleLog
  //   // console.log('结果是：', results.value)
  //   // 保存运行结果
  //   const isRight = isRunningRight(results.value)
  //   saveResult(isRight, results.value)
  // }
  // 将运行结果保存起来的方法
  // 判断运行结果是否正确的函数
  // 将运行结果保存起来的方法
  // 判断运行结果是否正确的函数

  // 保存运行结果
  const runningResults = ref({
    type: '',
    result: ''
  })
  // 保存运行结果的方法
  // const saveResult = (type, result) => {
  //   // 判断，如果输出的文本过长，那么判定执行超时
  //   if (result.length >= 1000 || result.includes('执行超时')||result.includes('Traceback')) {
  //     type = '运行失败'
  //     result = '执行超时!代码中存在死循环!'
  //     ElMessage({
  //       type:'error',
  //       message:'运行失败!'
  //     })
  //   } else if(type==='运行失败'){
  //     ElMessage({
  //       type:'error',
  //       message:'运行失败!'
  //     })
  //     // runningResults.value = {
  //     //   type,
  //     //   result
  //     // }
  //     console.log('运行失败的结果是:',runningResults.value.result)
  //   } else {
  //     ElMessage({
  //       type:'success',
  //       message:'运行成功!'
  //     })
  //     runningResults.value = {
  //       type,
  //       result
  //     }
  //   }
  // }
  // 清除所有输出的方法
  const clearResults = () => {
    runningResults.value = ''
  }

  return {
    userCode,
    initPython,
    results,
    runCode,
    runningResults,
    clearResults,
    userInput
  }
})
